/////////////////////////////////////////////////////////////////
/*

           __   _______ ___   ___ ___
     /\    \ \ / /  __ \__ \ / _ \__ \
    /  \    \ V /| |__) | ) | | | | ) |
   / /\ \    > < |  ___/ / /| | | |/ /
  / ____ \  / . \| |    / /_| |_| / /_
 /_/    \_\/_/ \_\_|   |____|\___/____|



MIT License

Copyright (c) 2019 lewis he

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

axp20x.h - Arduino library for X-Power AXP202 chip.
Created by Lewis he on April 1, 2019.
github:https://github.com/lewisxhe/AXP202X_Libraries
*/
/////////////////////////////////////////////////////////////////
#pragma once

#ifdef ARDUINO
#include <Arduino.h>
#include <Wire.h>
#else
#include <stdint.h>
#include <string.h>
#endif

// #define AXP_DEBUG_PORT  Serial
#ifdef AXP_DEBUG_PORT
#ifdef ARDUINO
#define AXP_DEBUG(fmt, ...)         AXP_DEBUG_PORT.printf_P((PGM_P)PSTR(fmt), ##__VA_ARGS__)
#else
#define AXP_DEBUG(...)              printf(__VA_ARGS__)
#endif

#else
#define AXP_DEBUG(...)
#endif

#ifndef RISING
#define RISING 0x01
#endif

#ifndef FALLING
#define FALLING 0x02
#endif

#ifdef _BV
#undef _BV
#endif
#define _BV(b)                                  (1ULL << (b))

//! Error Code
#define AXP_PASS                                (0)
#define AXP_FAIL                                (-1)
#define AXP_INVALID                             (-2)
#define AXP_NOT_INIT                            (-3)
#define AXP_NOT_SUPPORT                         (-4)
#define AXP_ARG_INVALID                         (-5)

//! Chip Address
#define AXP202_SLAVE_ADDRESS                    (0x34U)     //! 定制地址?(0x35U)
#define AXP192_SLAVE_ADDRESS                    (0x34U)
#define AXP173_SLAVE_ADDRESS                    (0x34U)

//! Chip ID
#define AXP202_CHIP_ID                          (0x41)
#define AXP192_CHIP_ID                          (0x03)
#define AXP173_CHIP_ID                          (0xAD)      //! Axp173 does not have  a chip ID, given a custom ID

//! Logic states
#define AXP202_ON                               (1)
#define AXP202_OFF                              (0)

//! REG MAP
#define AXP202_STATUS                           (0x00)
#define AXP202_MODE_CHGSTATUS                   (0x01)
#define AXP202_OTG_STATUS                       (0x02)
#define AXP202_IC_TYPE                          (0x03)
#define AXP202_DATA_BUFFER1                     (0x04)
#define AXP202_DATA_BUFFER2                     (0x05)
#define AXP202_DATA_BUFFER3                     (0x06)
#define AXP202_DATA_BUFFER4                     (0x07)
#define AXP202_DATA_BUFFER5                     (0x08)
#define AXP202_DATA_BUFFER6                     (0x09)
#define AXP202_DATA_BUFFER7                     (0x0A)
#define AXP202_DATA_BUFFER8                     (0x0B)
#define AXP202_DATA_BUFFER9                     (0x0C)
#define AXP202_DATA_BUFFERA                     (0x0D)
#define AXP202_DATA_BUFFERB                     (0x0E)
#define AXP202_DATA_BUFFERC                     (0x0F)
#define AXP202_LDO234_DC23_CTL                  (0x12)
#define AXP202_DC2OUT_VOL                       (0x23)
#define AXP202_LDO3_DC2_DVM                     (0x25)
#define AXP202_DC3OUT_VOL                       (0x27)
#define AXP202_LDO24OUT_VOL                     (0x28)
#define AXP202_LDO3OUT_VOL                      (0x29)
#define AXP202_IPS_SET                          (0x30)
#define AXP202_VOFF_SET                         (0x31)
#define AXP202_OFF_CTL                          (0x32)
#define AXP202_CHARGE1                          (0x33)
#define AXP202_CHARGE2                          (0x34)
#define AXP202_BACKUP_CHG                       (0x35)
#define AXP202_POK_SET                          (0x36)
#define AXP202_DCDC_FREQSET                     (0x37)
#define AXP202_VLTF_CHGSET                      (0x38)
#define AXP202_VHTF_CHGSET                      (0x39)
#define AXP202_APS_WARNING1                     (0x3A)
#define AXP202_APS_WARNING2                     (0x3B)
#define AXP202_TLTF_DISCHGSET                   (0x3C)
#define AXP202_THTF_DISCHGSET                   (0x3D)
#define AXP202_DCDC_MODESET                     (0x80)
#define AXP202_ADC_EN1                          (0x82)
#define AXP202_ADC_EN2                          (0x83)
#define AXP202_ADC_SPEED                        (0x84)
#define AXP202_ADC_INPUTRANGE                   (0x85)
#define AXP202_ADC_IRQ_RETFSET                  (0x86)
#define AXP202_ADC_IRQ_FETFSET                  (0x87)
#define AXP202_TIMER_CTL                        (0x8A)
#define AXP202_VBUS_DET_SRP                     (0x8B)
#define AXP202_HOTOVER_CTL                      (0x8F)
#define AXP202_GPIO0_CTL                        (0x90)
#define AXP202_GPIO0_VOL                        (0x91)
#define AXP202_GPIO1_CTL                        (0x92)
#define AXP202_GPIO2_CTL                        (0x93)
#define AXP202_GPIO012_SIGNAL                   (0x94)
#define AXP202_GPIO3_CTL                        (0x95)
#define AXP202_INTEN1                           (0x40)
#define AXP202_INTEN2                           (0x41)
#define AXP202_INTEN3                           (0x42)
#define AXP202_INTEN4                           (0x43)
#define AXP202_INTEN5                           (0x44)
#define AXP202_INTSTS1                          (0x48)
#define AXP202_INTSTS2                          (0x49)
#define AXP202_INTSTS3                          (0x4A)
#define AXP202_INTSTS4                          (0x4B)
#define AXP202_INTSTS5                          (0x4C)

//Irq control register
#define AXP192_INTEN1                           (0x40)
#define AXP192_INTEN2                           (0x41)
#define AXP192_INTEN3                           (0x42)
#define AXP192_INTEN4                           (0x43)
#define AXP192_INTEN5                           (0x4A)
//Irq status register
#define AXP192_INTSTS1                          (0x44)
#define AXP192_INTSTS2                          (0x45)
#define AXP192_INTSTS3                          (0x46)
#define AXP192_INTSTS4                          (0x47)
#define AXP192_INTSTS5                          (0x4D)

#define AXP192_DC1_VLOTAGE                      (0x26)
#define AXP192_LDO23OUT_VOL                     (0x28)
#define AXP192_GPIO0_CTL                        (0x90)
#define AXP192_GPIO0_VOL                        (0x91)
#define AXP192_GPIO1_CTL                        (0X92)
#define AXP192_GPIO2_CTL                        (0x93)
#define AXP192_GPIO012_SIGNAL                   (0x94)
#define AXP192_GPIO34_CTL                       (0x95)



/* axp 192/202 adc data register */
#define AXP202_BAT_AVERVOL_H8                   (0x78)
#define AXP202_BAT_AVERVOL_L4                   (0x79)
#define AXP202_BAT_AVERCHGCUR_H8                (0x7A)
#define AXP202_BAT_AVERCHGCUR_L4                (0x7B)
#define AXP202_BAT_AVERCHGCUR_L5                (0x7B)
#define AXP202_ACIN_VOL_H8                      (0x56)
#define AXP202_ACIN_VOL_L4                      (0x57)
#define AXP202_ACIN_CUR_H8                      (0x58)
#define AXP202_ACIN_CUR_L4                      (0x59)
#define AXP202_VBUS_VOL_H8                      (0x5A)
#define AXP202_VBUS_VOL_L4                      (0x5B)
#define AXP202_VBUS_CUR_H8                      (0x5C)
#define AXP202_VBUS_CUR_L4                      (0x5D)
#define AXP202_INTERNAL_TEMP_H8                 (0x5E)
#define AXP202_INTERNAL_TEMP_L4                 (0x5F)
#define AXP202_TS_IN_H8                         (0x62)
#define AXP202_TS_IN_L4                         (0x63)
#define AXP202_GPIO0_VOL_ADC_H8                 (0x64)
#define AXP202_GPIO0_VOL_ADC_L4                 (0x65)
#define AXP202_GPIO1_VOL_ADC_H8                 (0x66)
#define AXP202_GPIO1_VOL_ADC_L4                 (0x67)

#define AXP202_BAT_AVERDISCHGCUR_H8             (0x7C)
#define AXP202_BAT_AVERDISCHGCUR_L5             (0x7D)
#define AXP202_APS_AVERVOL_H8                   (0x7E)
#define AXP202_APS_AVERVOL_L4                   (0x7F)
#define AXP202_INT_BAT_CHGCUR_H8                (0xA0)
#define AXP202_INT_BAT_CHGCUR_L4                (0xA1)
#define AXP202_EXT_BAT_CHGCUR_H8                (0xA2)
#define AXP202_EXT_BAT_CHGCUR_L4                (0xA3)
#define AXP202_INT_BAT_DISCHGCUR_H8             (0xA4)
#define AXP202_INT_BAT_DISCHGCUR_L4             (0xA5)
#define AXP202_EXT_BAT_DISCHGCUR_H8             (0xA6)
#define AXP202_EXT_BAT_DISCHGCUR_L4             (0xA7)
#define AXP202_BAT_CHGCOULOMB3                  (0xB0)
#define AXP202_BAT_CHGCOULOMB2                  (0xB1)
#define AXP202_BAT_CHGCOULOMB1                  (0xB2)
#define AXP202_BAT_CHGCOULOMB0                  (0xB3)
#define AXP202_BAT_DISCHGCOULOMB3               (0xB4)
#define AXP202_BAT_DISCHGCOULOMB2               (0xB5)
#define AXP202_BAT_DISCHGCOULOMB1               (0xB6)
#define AXP202_BAT_DISCHGCOULOMB0               (0xB7)
#define AXP202_COULOMB_CTL                      (0xB8)
#define AXP202_BAT_POWERH8                      (0x70)
#define AXP202_BAT_POWERM8                      (0x71)
#define AXP202_BAT_POWERL8                      (0x72)

#define AXP202_VREF_TEM_CTRL                    (0xF3)
#define AXP202_BATT_PERCENTAGE                  (0xB9)

/* bit definitions for AXP events, irq event */
/*  AXP202  */
#define AXP202_IRQ_USBLO                        (1)
#define AXP202_IRQ_USBRE                        (2)
#define AXP202_IRQ_USBIN                        (3)
#define AXP202_IRQ_USBOV                        (4)
#define AXP202_IRQ_ACRE                         (5)
#define AXP202_IRQ_ACIN                         (6)
#define AXP202_IRQ_ACOV                         (7)

#define AXP202_IRQ_TEMLO                        (8)
#define AXP202_IRQ_TEMOV                        (9)
#define AXP202_IRQ_CHAOV                        (10)
#define AXP202_IRQ_CHAST                        (11)
#define AXP202_IRQ_BATATOU                      (12)
#define AXP202_IRQ_BATATIN                      (13)
#define AXP202_IRQ_BATRE                        (14)
#define AXP202_IRQ_BATIN                        (15)

#define AXP202_IRQ_POKLO                        (16)
#define AXP202_IRQ_POKSH                        (17)
#define AXP202_IRQ_LDO3LO                       (18)
#define AXP202_IRQ_DCDC3LO                      (19)
#define AXP202_IRQ_DCDC2LO                      (20)
#define AXP202_IRQ_CHACURLO                     (22)
#define AXP202_IRQ_ICTEMOV                      (23)

#define AXP202_IRQ_EXTLOWARN2                   (24)
#define AXP202_IRQ_EXTLOWARN1                   (25)
#define AXP202_IRQ_SESSION_END                  (26)
#define AXP202_IRQ_SESS_AB_VALID                (27)
#define AXP202_IRQ_VBUS_UN_VALID                (28)
#define AXP202_IRQ_VBUS_VALID                   (29)
#define AXP202_IRQ_PDOWN_BY_NOE                 (30)
#define AXP202_IRQ_PUP_BY_NOE                   (31)

#define AXP202_IRQ_GPIO0TG                      (32)
#define AXP202_IRQ_GPIO1TG                      (33)
#define AXP202_IRQ_GPIO2TG                      (34)
#define AXP202_IRQ_GPIO3TG                      (35)
#define AXP202_IRQ_PEKFE                        (37)
#define AXP202_IRQ_PEKRE                        (38)
#define AXP202_IRQ_TIMER                        (39)

//Signal Capture
#define AXP202_BATT_VOLTAGE_STEP                (1.1F)
#define AXP202_BATT_DISCHARGE_CUR_STEP          (0.5F)
#define AXP202_BATT_CHARGE_CUR_STEP             (0.5F)
#define AXP202_ACIN_VOLTAGE_STEP                (1.7F)
#define AXP202_ACIN_CUR_STEP                    (0.625F)
#define AXP202_VBUS_VOLTAGE_STEP                (1.7F)
#define AXP202_VBUS_CUR_STEP                    (0.375F)
#define AXP202_INTERNAL_TEMP_STEP               (0.1F)
#define AXP202_APS_VOLTAGE_STEP                 (1.4F)
#define AXP202_TS_PIN_OUT_STEP                  (0.8F)
#define AXP202_GPIO0_STEP                       (0.5F)
#define AXP202_GPIO1_STEP                       (0.5F)
// AXP192 only
#define AXP202_GPIO2_STEP                       (0.5F)
#define AXP202_GPIO3_STEP                       (0.5F)

// AXP173
#define AXP173_EXTEN_DC2_CTL                    (0x10)
#define AXP173_CTL_DC2_BIT                      (0)
#define AXP173_CTL_EXTEN_BIT                    (2)
#define AXP173_DC1_VLOTAGE                      (0x26)
#define AXP173_LDO4_VLOTAGE                     (0x27)

#define FORCED_OPEN_DCDC3(x)                    (x |= (AXP202_ON << AXP202_DCDC3))
#define IS_OPEN(reg, channel)                   (bool)(reg & _BV(channel))


#define AXP202_VOFF_MASK                        (0x07)
#define AXP202_LIMIT_MASK                       (0x03)
#define AXP192_LIMIT_MASK                       (0x01)
#define AXP192_LIMIT_EN_MASK                    (0x02)

enum {
    AXP202_EXTEN    = 0,
    AXP202_DCDC3    = 1,
    AXP202_LDO2     = 2,
    AXP202_LDO4     = 3,
    AXP202_DCDC2    = 4,
    AXP202_LDO3     = 6,
    AXP202_OUTPUT_MAX,
};

enum {
    AXP192_DCDC1    = 0,
    AXP192_DCDC3    = 1,
    AXP192_LDO2     = 2,
    AXP192_LDO3     = 3,
    AXP192_DCDC2    = 4,
    AXP192_EXTEN    = 6,
    AXP192_OUTPUT_MAX,
};

enum {
    AXP173_DCDC1    = 0,
    AXP173_LDO4     = 1,
    AXP173_LDO2     = 2,
    AXP173_LDO3     = 3,
    AXP173_DCDC2    = 4,
    AXP173_EXTEN    = 6,
    AXP173_OUTPUT_MAX,
};

typedef enum {
    AXP202_STARTUP_TIME_128MS,
    AXP202_STARTUP_TIME_3S,
    AXP202_STARTUP_TIME_1S,
    AXP202_STARTUP_TIME_2S,
} axp202_startup_time_t;

typedef enum {
    AXP192_STARTUP_TIME_128MS,
    AXP192_STARTUP_TIME_512MS,
    AXP192_STARTUP_TIME_1S,
    AXP192_STARTUP_TIME_2S,
} axp192_startup_time_t;

typedef enum {
    AXP_LONGPRESS_TIME_1S,
    AXP_LONGPRESS_TIME_1S5,
    AXP_LONGPRESS_TIME_2S,
    AXP_LONGPRESS_TIME_2S5,
} axp_longPress_time_t;

typedef enum {
    AXP_POWER_OFF_TIME_4S,
    AXP_POWER_OFF_TIME_6S,
    AXP_POWER_OFF_TIME_8S,
    AXP_POWER_OFF_TIME_10S,
} axp_poweroff_time_t;

//REG 33H: Charging control 1 Charging target-voltage setting
typedef enum {
    AXP202_TARGET_VOL_4_1V,
    AXP202_TARGET_VOL_4_15V,
    AXP202_TARGET_VOL_4_2V,
    AXP202_TARGET_VOL_4_36V
} axp_chargeing_vol_t;

//REG 82H: ADC Enable 1 register Parameter
typedef enum {
    AXP202_BATT_VOL_ADC1    = _BV(7),
    AXP202_BATT_CUR_ADC1    = _BV(6),
    AXP202_ACIN_VOL_ADC1    = _BV(5),
    AXP202_ACIN_CUR_ADC1    = _BV(4),
    AXP202_VBUS_VOL_ADC1    = _BV(3),
    AXP202_VBUS_CUR_ADC1    = _BV(2),
    AXP202_APS_VOL_ADC1     = _BV(1),
    AXP202_TS_PIN_ADC1      = _BV(0)
} axp_adc1_func_t;

// REG 83H: ADC Enable 2 register Parameter
typedef enum {
    AXP202_TEMP_MONITORING_ADC2 = _BV(7),
    AXP202_GPIO1_FUNC_ADC2      = _BV(3),
    AXP202_GPIO0_FUNC_ADC2      = _BV(2)
} axp_adc2_func_t;

typedef enum {
    AXP202_LDO3_MODE_LDO,
    AXP202_LDO3_MODE_DCIN
} axp202_ldo3_mode_t;

typedef enum {
    //! IRQ1 REG 40H
    AXP202_VBUS_VHOLD_LOW_IRQ       = _BV(1),   //VBUS is available, but lower than V HOLD, IRQ enable
    AXP202_VBUS_REMOVED_IRQ         = _BV(2),   //VBUS removed, IRQ enable
    AXP202_VBUS_CONNECT_IRQ         = _BV(3),   //VBUS connected, IRQ enable
    AXP202_VBUS_OVER_VOL_IRQ        = _BV(4),   //VBUS over-voltage, IRQ enable
    AXP202_ACIN_REMOVED_IRQ         = _BV(5),   //ACIN removed, IRQ enable
    AXP202_ACIN_CONNECT_IRQ         = _BV(6),   //ACIN connected, IRQ enable
    AXP202_ACIN_OVER_VOL_IRQ        = _BV(7),   //ACIN over-voltage, IRQ enable

    //! IRQ2 REG 41H
    AXP202_BATT_LOW_TEMP_IRQ        = _BV(8),   //Battery low-temperature, IRQ enable
    AXP202_BATT_OVER_TEMP_IRQ       = _BV(9),   //Battery over-temperature, IRQ enable
    AXP202_CHARGING_FINISHED_IRQ    = _BV(10),  //Charge finished, IRQ enable
    AXP202_CHARGING_IRQ             = _BV(11),  //Be charging, IRQ enable
    AXP202_BATT_EXIT_ACTIVATE_IRQ   = _BV(12),  //Exit battery activate mode, IRQ enable
    AXP202_BATT_ACTIVATE_IRQ        = _BV(13),  //Battery activate mode, IRQ enable
    AXP202_BATT_REMOVED_IRQ         = _BV(14),  //Battery removed, IRQ enable
    AXP202_BATT_CONNECT_IRQ         = _BV(15),  //Battery connected, IRQ enable

    //! IRQ3 REG 42H
    AXP202_PEK_LONGPRESS_IRQ        = _BV(16),  //PEK long press, IRQ enable
    AXP202_PEK_SHORTPRESS_IRQ       = _BV(17),  //PEK short press, IRQ enable
    AXP202_LDO3_LOW_VOL_IRQ         = _BV(18),  //LDO3output voltage is lower than the set value, IRQ enable
    AXP202_DC3_LOW_VOL_IRQ          = _BV(19),  //DC-DC3output voltage is lower than the set value, IRQ enable
    AXP202_DC2_LOW_VOL_IRQ          = _BV(20),  //DC-DC2 output voltage is lower than the set value, IRQ enable
    //**Reserved and unchangeable BIT 5
    AXP202_CHARGE_LOW_CUR_IRQ       = _BV(22),  //Charge current is lower than the set current, IRQ enable
    AXP202_CHIP_TEMP_HIGH_IRQ       = _BV(23),  //AXP202 internal over-temperature, IRQ enable

    //! IRQ4 REG 43H
    AXP202_APS_LOW_VOL_LEVEL2_IRQ   = _BV(24),  //APS low-voltage, IRQ enable（LEVEL2）
    APX202_APS_LOW_VOL_LEVEL1_IRQ   = _BV(25),  //APS low-voltage, IRQ enable（LEVEL1）
    AXP202_VBUS_SESSION_END_IRQ     = _BV(26),  //VBUS Session End IRQ enable
    AXP202_VBUS_SESSION_AB_IRQ      = _BV(27),  //VBUS Session A/B IRQ enable
    AXP202_VBUS_INVALID_IRQ         = _BV(28),  //VBUS invalid, IRQ enable
    AXP202_VBUS_VAILD_IRQ           = _BV(29),  //VBUS valid, IRQ enable
    AXP202_NOE_OFF_IRQ              = _BV(30),  //N_OE shutdown, IRQ enable
    AXP202_NOE_ON_IRQ               = _BV(31),  //N_OE startup, IRQ enable

    //! IRQ5 REG 44H
    AXP202_GPIO0_EDGE_TRIGGER_IRQ   = _BV(32),  //GPIO0 input edge trigger, IRQ enable
    AXP202_GPIO1_EDGE_TRIGGER_IRQ   = _BV(33),  //GPIO1input edge trigger or ADC input, IRQ enable
    AXP202_GPIO2_EDGE_TRIGGER_IRQ   = _BV(34),  //GPIO2input edge trigger, IRQ enable
    AXP202_GPIO3_EDGE_TRIGGER_IRQ   = _BV(35),  //GPIO3 input edge trigger, IRQ enable
    //**Reserved and unchangeable BIT 4
    AXP202_PEK_FALLING_EDGE_IRQ     = _BV(37),  //PEK press falling edge, IRQ enable
    AXP202_PEK_RISING_EDGE_IRQ      = _BV(38),  //PEK press rising edge, IRQ enable
    AXP202_TIMER_TIMEOUT_IRQ        = _BV(39),  //Timer timeout, IRQ enable

    AXP202_ALL_IRQ                  = (0xFFFFFFFFFFULL)
} axp_irq_t;

typedef enum {
    AXP202_LDO4_1250MV,
    AXP202_LDO4_1300MV,
    AXP202_LDO4_1400MV,
    AXP202_LDO4_1500MV,
    AXP202_LDO4_1600MV,
    AXP202_LDO4_1700MV,
    AXP202_LDO4_1800MV,
    AXP202_LDO4_1900MV,
    AXP202_LDO4_2000MV,
    AXP202_LDO4_2500MV,
    AXP202_LDO4_2700MV,
    AXP202_LDO4_2800MV,
    AXP202_LDO4_3000MV,
    AXP202_LDO4_3100MV,
    AXP202_LDO4_3200MV,
    AXP202_LDO4_3300MV,
    AXP202_LDO4_MAX,
} axp_ldo4_table_t;

typedef enum {
    AXP202_LDO5_1800MV,
    AXP202_LDO5_2500MV,
    AXP202_LDO5_2800MV,
    AXP202_LDO5_3000MV,
    AXP202_LDO5_3100MV,
    AXP202_LDO5_3300MV,
    AXP202_LDO5_3400MV,
    AXP202_LDO5_3500MV,
} axp_ldo5_table_t;

typedef enum {
    AXP20X_LED_CHARGING_CTL = 0,
    AXP20X_LED_REG_32H_CTL  = 1,
} axp_chgled_control_t;

typedef enum {
    AXP20X_LED_OFF,
    AXP20X_LED_BLINK_1HZ,
    AXP20X_LED_BLINK_4HZ,
    AXP20X_LED_LOW_LEVEL,   //Still Light
} axp_chgled_mode_t;

typedef enum {
    AXP20X_LED_LIGHT_WHEN_CHARGING = 0,
    AXP20X_LED_BLINK_WHEN_CHARGING = 1,
} axp_chgled_charging_mode_t;

typedef enum {
    AXP_ADC_SAMPLING_RATE_25HZ  = 0,
    AXP_ADC_SAMPLING_RATE_50HZ  = 1,
    AXP_ADC_SAMPLING_RATE_100HZ = 2,
    AXP_ADC_SAMPLING_RATE_200HZ = 3,
} axp_adc_sampling_rate_t;

typedef enum {
    AXP_TS_PIN_CURRENT_20UA = 0,
    AXP_TS_PIN_CURRENT_40UA = 1,
    AXP_TS_PIN_CURRENT_60UA = 2,
    AXP_TS_PIN_CURRENT_80UA = 3,
} axp_ts_pin_current_t;

typedef enum {
    AXP_TS_PIN_FUNCTION_BATT    = 0,
    AXP_TS_PIN_FUNCTION_ADC     = 1,
} axp_ts_pin_function_t;

typedef enum {
    AXP_TS_PIN_MODE_DISABLE     = 0,
    AXP_TS_PIN_MODE_CHARGING    = 1,
    AXP_TS_PIN_MODE_SAMPLING    = 2,
    AXP_TS_PIN_MODE_ENABLE      = 3,
} axp_ts_pin_mode_t;

//! Only AXP192 and AXP202 have gpio function
typedef enum {
    AXP_GPIO_0,
    AXP_GPIO_1,
    AXP_GPIO_2,
    AXP_GPIO_3,
    AXP_GPIO_4,
} axp_gpio_t;

typedef enum {
    AXP_IO_OUTPUT_LOW_MODE,
    AXP_IO_OUTPUT_HIGH_MODE,
    AXP_IO_INPUT_MODE,
    AXP_IO_LDO_MODE,
    AXP_IO_ADC_MODE,
    AXP_IO_FLOATING_MODE,
    AXP_IO_OPEN_DRAIN_OUTPUT_MODE,
    AXP_IO_PWM_OUTPUT_MODE,
    AXP_IO_EXTERN_CHARGING_CTRL_MODE,
} axp_gpio_mode_t;

typedef enum {
    AXP_IRQ_NONE,
    AXP_IRQ_RISING,
    AXP_IRQ_FALLING,
    AXP_IRQ_DOUBLE_EDGE,
} axp_gpio_irq_t;


typedef enum {
    AXP192_GPIO_1V8,
    AXP192_GPIO_1V9,
    AXP192_GPIO_2V0,
    AXP192_GPIO_2V1,
    AXP192_GPIO_2V2,
    AXP192_GPIO_2V3,
    AXP192_GPIO_2V4,
    AXP192_GPIO_2V5,
    AXP192_GPIO_2V6,
    AXP192_GPIO_2V7,
    AXP192_GPIO_2V8,
    AXP192_GPIO_2V9,
    AXP192_GPIO_3V0,
    AXP192_GPIO_3V1,
    AXP192_GPIO_3V2,
    AXP192_GPIO_3V3,
} axp192_gpio_voltage_t;

typedef enum {
    AXP1XX_CHARGE_CUR_100MA,
    AXP1XX_CHARGE_CUR_190MA,
    AXP1XX_CHARGE_CUR_280MA,
    AXP1XX_CHARGE_CUR_360MA,
    AXP1XX_CHARGE_CUR_450MA,
    AXP1XX_CHARGE_CUR_550MA,
    AXP1XX_CHARGE_CUR_630MA,
    AXP1XX_CHARGE_CUR_700MA,
    AXP1XX_CHARGE_CUR_780MA,
    AXP1XX_CHARGE_CUR_880MA,
    AXP1XX_CHARGE_CUR_960MA,
    AXP1XX_CHARGE_CUR_1000MA,
    AXP1XX_CHARGE_CUR_1080MA,
    AXP1XX_CHARGE_CUR_1160MA,
    AXP1XX_CHARGE_CUR_1240MA,
    AXP1XX_CHARGE_CUR_1320MA,
} axp1xx_charge_current_t;


typedef enum {
    AXP20X_VBUS_LIMIT_900MA,
    AXP20X_VBUS_LIMIT_500MA,
    AXP20X_VBUS_LIMIT_100MA,
    AXP20X_VBUS_LIMIT_OFF
} axp202_limit_setting_t;


typedef enum {
    AXP192_VBUS_LIMIT_500MA,
    AXP192_VBUS_LIMIT_100MA,
    AXP192_VBUS_LIMIT_OFF
} axp192_limit_setting_t;


typedef enum {
    AXP202_DCDC_AUTO_MODE,
    AXP202_DCDC_PWM_MODE
} axp202_dc_mode_t;

/**
 * @brief  Voltage rise slope control
 */
typedef enum {
    AXP202_VRC_LEVEL0,  // 25mV/15.625us=1.6mV/us
    AXP202_VRC_LEVEL1,  //25mV/31.250us=0.8mV/us
} axp202_vrc_control_t;

typedef enum {
    AXP202_BACKUP_VOLTAGE_3V1,
    AXP202_BACKUP_VOLTAGE_3V0,
    AXP202_BACKUP_VOLTAGE_3V6,
    AXP202_BACKUP_VOLTAGE_2V5,
} axp202_backup_voltage_t;

typedef enum {
    AXP202_BACKUP_CURRENT_50UA,
    AXP202_BACKUP_CURRENT_100UA,
    AXP202_BACKUP_CURRENT_200UA,
    AXP202_BACKUP_CURRENT_400UA,
} axp202_backup_current_t;

typedef enum {
    AXP202_PRECHARGE_MINUTES_40,
    AXP202_PRECHARGE_MINUTES_50,
    AXP202_PRECHARGE_MINUTES_60,
    AXP202_PRECHARGE_MINUTES_70,
} axp202_precharge_timeout_t;

typedef enum {
    AXP202_CONSTANT_CUR_TIMEOUT_HOURS_6,
    AXP202_CONSTANT_CUR_TIMEOUT_HOURS_8,
    AXP202_CONSTANT_CUR_TIMEOUT_HOURS_10,
    AXP202_CONSTANT_CUR_TIMEOUT_HOURS_12,
} axp202_constant_current_t;

typedef uint32_t (*axp_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len); //! 类型错误：int

class AXP20X_Class
{
public:

#ifdef ARDUINO
    int begin(TwoWire &port = Wire, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false);
#endif

    int begin(axp_com_fptr_t read_cb, axp_com_fptr_t write_cb, uint8_t addr = AXP202_SLAVE_ADDRESS, bool isAxp173 = false);

    // Power Output Control
    int setPowerOutPut(uint8_t channel, bool en);


    uint16_t    getDCDC1Voltage(void);                  //! Only AXP192 support and AXP173
    uint16_t    getDCDC2Voltage(void);
    uint16_t    getDCDC3Voltage(void);
    uint16_t    getLDO2Voltage(void);
    uint16_t    getLDO3Voltage(void);
    uint16_t    getLDO4Voltage(void);                   //! Only axp173/axp202 support

    int         setDCDC1Voltage(uint16_t mv);           //! Only AXP192 support and AXP173
    int         setDCDC2Voltage(uint16_t mv);
    int         setDCDC3Voltage(uint16_t mv);
    int         setLDO2Voltage(uint16_t mv);
    int         setLDO3Voltage(uint16_t mv);
    int         setLDO4Voltage(uint16_t mv);            //! Only axp173 support
    int         setLDO4Voltage(axp_ldo4_table_t param); //! Only axp202 support
    int         setLDO5Voltage(axp_ldo5_table_t vol);

    int         setLDO3Mode(axp202_ldo3_mode_t mode);   //! Only AXP202 support


    bool        isDCDC1Enable(void);    //Only axp192 chip
    bool        isDCDC2Enable(void);
    bool        isDCDC3Enable(void);

    bool        isLDO2Enable(void);
    bool        isLDO3Enable(void);
    bool        isLDO4Enable(void);

    bool        isChargingEnable(void);

    bool        isChargeingEnable(void) __attribute__((deprecated));
    bool        isBatteryConnect(void);
    bool        isCharging(void);
    bool        isChargeing(void) __attribute__((deprecated));
    bool        isVBUSPlug(void);
    bool        isExtenEnable(void);


    // ACIN overvoltage IRQ
    bool        isAcinOverVoltageIRQ(void);
    // ACIN access IRQ
    bool        isAcinPlugInIRQ(void);
    // ACIN out of IRQ
    bool        isAcinRemoveIRQ(void);
    // VBUS overvoltage IRQ
    bool        isVbusOverVoltageIRQ(void);
    // VBUS access IRQ
    bool        isVbusPlugInIRQ(void);
    // VBUS shifted out of IRQ
    bool        isVbusRemoveIRQ(void);
    // VBUS is available but less than V HOLD IRQ
    bool        isVbusLowVHOLDIRQ(void);

    // Battery access IRQ
    bool        isBattPlugInIRQ(void);
    // Battery removed IRQ
    bool        isBattRemoveIRQ(void);
    // Battery activation mode IRQ
    bool        isBattEnterActivateIRQ(void);
    // Exit battery activation mode IRQ
    bool        isBattExitActivateIRQ(void);
    // Charging IRQ
    bool        isChargingIRQ(void);
    // Charge complete IRQ
    bool        isChargingDoneIRQ(void);
    // Battery over temperature IRQ
    bool        isBattTempLowIRQ(void);
    // Battery temperature is too low IRQ
    bool        isBattTempHighIRQ(void);

    // IC internal overheating IRQ
    bool        isChipOvertemperatureIRQ(void);
    // The charging current is less than the set current IRQ
    bool        isChargingCurrentLessIRQ(void);
    // DC-DC2 output voltage is less than the set value IRQ
    bool        isDC2VoltageLessIRQ(void);
    // DC-DC3 output voltage is less than the set value IRQ
    bool        isDC3VoltageLessIRQ(void);
    // LDO3 output voltage is less than the set value IRQ
    bool        isLDO3VoltageLessIRQ(void);
    // PEK short key IRQ
    bool        isPEKShortPressIRQ(void);
    // PEK long key IRQ
    bool        isPEKLongtPressIRQ(void);

    // N_OE boot IRQ
    bool        isNOEPowerOnIRQ(void);
    // N_OE shutdown IRQ
    bool        isNOEPowerDownIRQ(void);
    // VBUS valid IRQ
    bool        isVBUSEffectiveIRQ(void);
    // VBUS invalid IRQ
    bool        isVBUSInvalidIRQ(void);
    // VBUS Session IRQ
    bool        isVUBSSessionIRQ(void);
    // VBUS Session End IRQ
    bool        isVUBSSessionEndIRQ(void);
    // APS low voltage IRQ enable (LEVEL1)
    bool        isLowVoltageLevel1IRQ(void);
    // APS low voltage IRQ enable (LEVEL2)
    bool        isLowVoltageLevel2IRQ(void);

    // Timer expired IRQ
    bool        isTimerTimeoutIRQ(void);
    // PEK key rising edge IRQ
    bool        isPEKRisingEdgeIRQ(void);
    // PEK key falling edge IRQ
    bool        isPEKFallingEdgeIRQ(void);
    // GPIO3 input edge trigger IRQ
    bool        isGPIO3InputEdgeTriggerIRQ(void);
    // GPIO2 input edge trigger IRQ
    bool        isGPIO2InputEdgeTriggerIRQ(void);
    // GPIO1 input edge trigger or ADC input IRQ
    bool        isGPIO1InputEdgeTriggerIRQ(void);
    // GPIO0 input edge trigger IRQ
    bool        isGPIO0InputEdgeTriggerIRQ(void);


    //! Group4 ADC data
    float       getAcinVoltage(void);
    float       getAcinCurrent(void);
    float       getVbusVoltage(void);
    float       getVbusCurrent(void);
    float       getTemp(void);
    float       getTSTemp(void);
    float       getGPIO0Voltage(void);
    float       getGPIO1Voltage(void);
    float       getBattInpower(void);
    float       getBattVoltage(void);
    float       getBattChargeCurrent(void);
    float       getBattDischargeCurrent(void);
    float       getSysIPSOUTVoltage(void);
    uint32_t    getBattChargeCoulomb(void);
    uint32_t    getBattDischargeCoulomb(void);
    float       getSettingChargeCurrent(void);

    int         getChargingTargetVoltage(axp_chargeing_vol_t &charging_target_voltage);
    int         setChargingTargetVoltage(axp_chargeing_vol_t param);
    int         enableCharging(bool en);
    int         enableChargeing(bool en) __attribute__((deprecated));


    int         adc1Enable(uint16_t params, bool en);
    int         adc2Enable(uint16_t params, bool en);

    int         setTScurrent(axp_ts_pin_current_t current);
    int         setTSfunction(axp_ts_pin_function_t func);
    int         setTSmode(axp_ts_pin_mode_t mode);


    int         setTimer(uint8_t minutes);
    int         offTimer(void);
    int         clearTimerStatus(void);
    bool        getTimerStatus(void);
    /**
     * param:   axp202_startup_time_t or axp192_startup_time_t
     */
    int         setStartupTime(uint8_t param);

    /**
     * param: axp_loonPress_time_t
     */
    int         setlongPressTime(uint8_t param);

    /**
     * @param  param: axp_poweroff_time_t
     */
    int         setShutdownTime(uint8_t param);
    int         setTimeOutShutdown(bool en);

    int         shutdown(void);
    int         setSleep(void);

    /**
     * params: axp_irq_t
     */
    int         enableIRQ(uint64_t params, bool en);
    int         readIRQ(void);
    void        clearIRQ(void);

    int         setChgLEDContrl(axp_chgled_control_t opt);
    int         setChgLEDMode(axp_chgled_mode_t mode);

    //! Only AXP202 support
    int         getBattPercentage(void);
    int         setMeteringSystem(bool en);

    int         debugCharging(void);
    int         debugStatus(void);
    int         limitingOff(void);

    int         setAdcSamplingRate(axp_adc_sampling_rate_t rate);
    uint8_t     getAdcSamplingRate(void);
    uint8_t     getCoulombRegister(void);
    float       getCoulombData(void);
    int         setCoulombRegister(uint8_t val);
    int         EnableCoulombcounter(void);
    int         DisableCoulombcounter(void);
    int         StopCoulombcounter(void);
    int         ClearCoulombcounter(void);

    int         setGPIOMode(axp_gpio_t gpio, axp_gpio_mode_t mode);
    int         setGPIOIrq(axp_gpio_t gpio, axp_gpio_irq_t irq);

    int         gpioWrite(axp_gpio_t gpio, uint8_t val);
    int         gpioRead(axp_gpio_t gpio);

    // When the chip is axp192 / 173, the allowed values are 0 ~ 15, corresponding to the axp1xx_charge_current_t enumeration
    // When the chip is axp202 allows maximum charging current of 1800mA, minimum 300mA
    int         getChargeControlCur(void);
    int         setChargeControlCur(uint16_t mA);

    uint16_t    getPowerDownVoltage(void);
    int         setPowerDownVoltage(uint16_t mv);
    int         setCurrentLimitControl(axp202_limit_setting_t opt);
    int         setCurrentLimitControl(axp192_limit_setting_t opt);

    int         setVWarningLevel1(uint16_t mv);
    int         setVWarningLevel2(uint16_t mv);

    uint16_t    getVWarningLevel1(void);
    uint16_t    getVWarningLevel2(void);

    int         setDCDCMode(axp202_dc_mode_t opt);
    axp202_dc_mode_t getDCDCMode(void);

    int         enableLDO3VRC(bool en);
    int         enableDC2VRC(bool en);
    int         setLDO3VRC(axp202_vrc_control_t opt);
    int         setDC2VRC(axp202_vrc_control_t opt);


    //Backup battery charge control
    int         setBackupChargeControl(bool en);
    int         setBackupChargeVoltage(axp202_backup_voltage_t opt);
    int         setBackupChargeCurrent(axp202_backup_current_t opt);


    // Precharge timeout setting
    int         setPrechargeTimeout(axp202_precharge_timeout_t opt);
    // Set timeout in constant current mode
    int         setConstantCurrentTimeout(axp202_constant_current_t opt);
    // Set CHGLED mode when charging
    int         setChgLEDChargingMode(axp_chgled_charging_mode_t opt);

private:
    uint16_t _getRegistH8L5(uint8_t regh8, uint8_t regl5);
    uint16_t _getRegistResult(uint8_t regh8, uint8_t regl4);

    int _readByte(uint8_t reg, uint8_t nbytes, uint8_t *data);
    int _writeByte(uint8_t reg, uint8_t nbytes, uint8_t *data);

    int _setGpioInterrupt(uint8_t *val, int mode, bool en);
    int _axp_probe(void);
    int _axp_irq_mask(axp_gpio_irq_t irq);

    int _axp192_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode);
    int _axp192_gpio_0_select( axp_gpio_mode_t mode);
    int _axp192_gpio_1_select( axp_gpio_mode_t mode);
    int _axp192_gpio_3_select( axp_gpio_mode_t mode);
    int _axp192_gpio_4_select( axp_gpio_mode_t mode);

    int _axp202_gpio_set(axp_gpio_t gpio, axp_gpio_mode_t mode);
    int _axp202_gpio_0_select( axp_gpio_mode_t mode);
    int _axp202_gpio_1_select( axp_gpio_mode_t mode);
    int _axp202_gpio_2_select( axp_gpio_mode_t mode);
    int _axp202_gpio_3_select( axp_gpio_mode_t mode);
    int _axp202_gpio_irq_set(axp_gpio_t gpio, axp_gpio_irq_t irq);
    int _axp202_gpio_write(axp_gpio_t gpio, uint8_t val);
    int _axp202_gpio_read(axp_gpio_t gpio);


    static const uint8_t startupParams[], longPressParams[], shutdownParams[], targetVolParams[];
    static uint8_t _outputReg;
    uint8_t _address, _irq[5], _chip_id, _gpio[4];
    bool _init = false;
    axp_com_fptr_t _read_cb = nullptr;
    axp_com_fptr_t _write_cb = nullptr;
#ifdef ARDUINO
    TwoWire *_i2cPort;
#endif
    bool _isAxp173;
};

extern AXP20X_Class axp;

